package com.leyou.order.util;

import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.order.config.PayConfig;
import com.leyou.order.enums.OrderStatusEnum;
import com.leyou.order.enums.PayStateEnum;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.mapper.OrderStatusMapper;
import com.leyou.order.pojo.Order;
import com.leyou.order.pojo.OrderStatus;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static com.github.wxpay.sdk.WXPayConstants.*;

@Slf4j
@Component
public class PayHelper {

    @Autowired
    private WXPay wxPay;

    @Autowired
    private PayConfig config;

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderStatusMapper statusMapper;

    public String createOrder(Long orderId,Long totalPay,String desc){
        try {
            Map<String,String> data = new HashMap<>();

            data.put("body",desc);//商品的描述
            data.put("out_trade_no",orderId.toString());//订单编号
            data.put("total_fee",totalPay.toString());//金额 单位分
            data.put("spbill_create_ip","127.0.0.1");//调用微信支付的终端ip
            data.put("notify_url",config.getNotifUrl());//回调地址
            data.put("trade_type","NATIVE");//支付方式 扫描支付

            //发送请求产生支付链接
            Map<String,String> result = wxPay.unifiedOrder(data);

            //判断通讯和业务标识
            isSuccess(result);

            String url = result.get("code_url");
            return  url;

        }catch (Exception e){
            log.error("[微信下单] 创建预交易订单异常失败",e);
            return null;
        }
    }

    public void isSuccess(Map<String,String> result){
        String returnCode = result.get("return_code");
        //判断通信标识
        if (FAIL.equals(returnCode)) {
            log.error("[微信下单] 微信 下单通信失败，失败原因:{}",result.get("return_msg"));
            throw new LyException(ExceptionEnum.WX_PAY_ORDER_FAIL);
        }


        //判断业务标识
        if (FAIL.equals(returnCode)) {
            log.error("[微信下单] 微信下单业务失败，错误码:{}，错误原因:{}",
                    result.get("err_code"),result.get("err_code_des"));
            throw new LyException(ExceptionEnum.WX_PAY_ORDER_FAIL);
        }
    }

    /**
     * 签名校验
     * @param data
     */
    public void isSValidSign(Map<String, String> data) {

        try {
            //1.重新生成签名
            String sign1 = WXPayUtil.generateSignature(data, config.getKey(), SignType.HMACSHA256);
            String sign2 = WXPayUtil.generateSignature(data, config.getKey(), SignType.HMACSHA256);

            String sign = data.get("sign");
            //2.和传入的签名进行比较

            if(!StringUtils.equals(sign1, sign) && !StringUtils.equals(sign2, sign)){
                 throw  new LyException(ExceptionEnum.INVALID_SIGN_ERROR);
            }
        }catch (Exception e){
            throw  new LyException(ExceptionEnum.INVALID_SIGN_ERROR);
        }


    }

    /**
     * 查询订单状态
     * @param orderId
     */
    public PayStateEnum queryPayState(Long orderId) {

        try {
            //组织请求参数
            Map<String, String> data = new HashMap<>();
            data.put("out_trade_no", orderId.toString());
            //查询状态
            Map<String, String> result = wxPay.orderQuery(data);

            //校验通讯状态。
            isSValidSign(result);


            //校验签名
            isSValidSign(result);

            //校验金额
            String totalFeeStr = result.get("total_fee");
            String tradeNo = result.get("out_trade_no");
            if (StringUtils.isEmpty(totalFeeStr) || StringUtils.isEmpty(tradeNo)) {
                throw  new LyException(ExceptionEnum.INVALID_ORDER_PARAM);
            }

            //3.1获得结果中的金额
            Long totalFee = Long.valueOf(totalFeeStr);

            //3.2获得订单中的金额


            Order order = orderMapper.selectByPrimaryKey(orderId);

            if (totalFee != order.getActualPay()) {
                //金额不符
                throw  new LyException(ExceptionEnum.INVALID_ORDER_PARAM);
            }

            /**
             * 验证状态
             * SUCCESS 支持成功
             *
             * REEFUND 转入退款
             *
             *
             * CLOSED 已关闭
             *
             * REVOKED  已撤销（刷卡支付）
             *
             * USERPAYING 支付中
             *
             * PAYERROR
             */
            String state = result.get("trade_state");

            if(SUCCESS.equals(state)){
                //支付成功

                //4.修改订单状态。
                OrderStatus orderStatus = new OrderStatus();
                orderStatus.setOrderId(orderId);
                orderStatus.setStatus(OrderStatusEnum.PAYED.value());
                orderStatus.setPaymentTime(new Date());
                int count = statusMapper.updateByPrimaryKeySelective(orderStatus);
                if (count != 1) {
                    throw  new LyException(ExceptionEnum.UPDATE_ORDER_STATUS_ERROR);
                }
                return  PayStateEnum.SUCCESS;
            }

            //未支付状态
            if ("NOTPAY".equals(state) || "USERPAYING".equals(state)){
                return PayStateEnum.NOT_PAY;
            }

            //其他的情况
            return  PayStateEnum.FAIL;

        }catch (Exception e){
            return  PayStateEnum.NOT_PAY;
        }
    }
}
